﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows;

namespace NielsHebling.UnitTestResultViewerForSL.Core.Logic
{
    public class StatLightManager
    {
        #region Singleton
        static StatLightManager _instance = null;
        static readonly object _lockObj = new object();        

        public static StatLightManager Instance
        {
            get 
            {
                lock (_lockObj)
                {
                    if (_instance == null)
                    {
                        _instance = new StatLightManager();
                        _instance.SetStatLightPath();
                        _instance.IdentifyStatLightVersion();
                    }
                    return _instance;
                }
            }
        }

        private StatLightManager()
        {

        }
        #endregion

        public const string STATLIGHT_NAME = "StatLight";
        public string StatLightApplicationPath { get; set; }        
        private string _statLightDirectory;
        public StatLightVersion StatLightVersion { get; set; }

        private void SetStatLightPath()
        {
            DirectoryInfo diAppLocal = new DirectoryInfo(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + "\\" + STATLIGHT_NAME);
            if (diAppLocal.Exists)
            {
                _instance._statLightDirectory = diAppLocal.FullName;                
                return;
            }
            else
            {
                DirectoryInfo diProgramFiles = new DirectoryInfo(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles) + "\\" + STATLIGHT_NAME);
                if (diProgramFiles.Exists)
                {
                    _instance._statLightDirectory = diProgramFiles.FullName;                    
                    return;
                }
            }
            //Default, even if not exist, for error message.
            _instance._statLightDirectory = diAppLocal.FullName;
        }

        private void IdentifyStatLightVersion()
        { 
            FileInfo fi = new FileInfo(this._statLightDirectory+"\\"+STATLIGHT_NAME+".exe");
            if(fi.Exists)
            {
                FileVersionInfo fvI = FileVersionInfo.GetVersionInfo(fi.FullName);
                //Does not support multiple xap files
                if (fvI.FileMajorPart == 1 && fvI.FileMinorPart == 1)
                {
                    StatLightVersion = Logic.StatLightVersion.v11;
                    return;
                }
                    //Supports multiple xap files
                else if (((fvI.FileMajorPart == 1) && (fvI.FileMinorPart >= 2)) || (fvI.FileMajorPart > 1))
                {
                    StatLightVersion = Logic.StatLightVersion.v12;
                    return;
                }
                else
                {
                    StatLightVersion = Logic.StatLightVersion.None;
                    return;
                }
            }
            StatLightVersion = Logic.StatLightVersion.None;
            return;
        }

        public bool IsStatLightInstalled()
        {
            DirectoryInfo di = new DirectoryInfo(_statLightDirectory);
            if (di.Exists)
            {
                FileInfo fi = new FileInfo(_statLightDirectory + "\\" + STATLIGHT_NAME + ".exe");
                if (fi.Exists)
                {
                    return true;
                }
            }
            return false;
        }

        public void ShowMessageBoxOnNotFound()
        {
            if (!StatLightManager.Instance.IsStatLightInstalled())
            {
                MessageBox.Show("'StatLight' not found in:\n"
                    + System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles) + "\\" + StatLightManager.STATLIGHT_NAME + "\\" + StatLightManager.STATLIGHT_NAME + ".exe\n\n"
                    + "1.) Please download 'StatLight' from http://statlight.codeplex.com/ \n"
                    + "2.) Extract the content in " + System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles) + "\\" + StatLightManager.STATLIGHT_NAME,
                    "Unit Test Resultviewer for Silverlight - Required installation not found.",
                    MessageBoxButton.OK,
                    MessageBoxImage.Error);
            }
        }

        public string RunTest(string xapName)
        {
            return RunTest(xapName, string.Empty);
        }

        public string RunMultipleTests(string testResultsOutputPath, List<string> xapList)
        {
            return RunMultipleTests(testResultsOutputPath, xapList, string.Empty);
        }

        public string RunTest(string xapName, string resultOutput)
        {
            if (IsStatLightInstalled())
            {
                string result;
                if (String.IsNullOrWhiteSpace(resultOutput))
                {
                    result = xapName + "_TestResult.xml";
                }
                else
                {
                    result = resultOutput;
                }

                FileInfo fi = new FileInfo(xapName);
                if (fi.Exists)
                {
                    StringBuilder argsBuilder = new StringBuilder();
                    argsBuilder.Append("-x=");
                    argsBuilder.Append("\"" + fi.FullName + "\"");
                    argsBuilder.Append(" -r=");
                    argsBuilder.Append("\"" + result + "\"");

                    Test(argsBuilder.ToString());
                    return result;
                }
            }
            return string.Empty;
        }

        public string RunMultipleTests(string testResultsOutputPath, List<string> xapList, string resultOutput)
        {
            if (IsStatLightInstalled())
            {
                string result;
                if (String.IsNullOrWhiteSpace(resultOutput))
                {
                    result = testResultsOutputPath + "\\Combined_TestResult.xml";
                }
                else
                {
                    result = resultOutput;
                }

                StringBuilder argsBuilder = new StringBuilder();
                foreach (string xapName in xapList)
                {
                    FileInfo fi = new FileInfo(xapName);
                    if (fi.Exists)
                    {                        
                        argsBuilder.Append("-x=");
                        argsBuilder.Append("\"" + fi.FullName + "\"");
                        argsBuilder.Append(" ");                      
                    }
                }
                
                argsBuilder.Append("-r=");
                argsBuilder.Append("\"" + result + "\"");  

                Test(argsBuilder.ToString());
                return result;
            }
            return string.Empty;
        }

        private void Test(string arguments)
        {
            string statLightExeFilePath = _statLightDirectory + "\\" + STATLIGHT_NAME + ".exe";
            // Start the child process.
            Process process = new Process()
            {
                StartInfo = new ProcessStartInfo()
                {
                    // Redirect the output stream of the child process.
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    FileName = statLightExeFilePath,
                    Arguments = arguments,
                    CreateNoWindow = true,
                    WindowStyle = ProcessWindowStyle.Hidden
                }
            };

            VsShellAbstractionLayer.Instance.Trace(string.Format("\"{0}\" {1}", statLightExeFilePath,  arguments));

            process.Start();
            string output = process.StandardOutput.ReadToEnd();
            process.WaitForExit();
            VsShellAbstractionLayer.Instance.Trace(output);
        }       
    }

    public enum StatLightVersion
    {
        None = 0,
        v11 = 1,
        v12 = 2
    }
}
